﻿using System;
using System.Collections.Generic;
using System.Data.Objects.DataClasses;
using System.Linq;
using System.Text;
using System.Web.DynamicData;
using System.Web.Security;
using System.Web.UI.WebControls;
using NotAClue.ComponentModel.DataAnnotations;
using NotAClue.Web;
using NotAClue.Web.DynamicData;

namespace DD_Extensions
{
    public partial class ChildrenListField : FieldTemplateUserControl
    {
        protected MetaTable table;

        protected ShowChildTablesAttribute _showChildren;

        private new MetaChildrenColumn Column
        {
            get { return (MetaChildrenColumn)base.Column; }
        }

        private MetaForeignKeyColumn ChildMetaForeignKeyColumn
        {
            get { return (MetaForeignKeyColumn)Column.ColumnInOtherTable; }
        }

        //private String[] DisplayColumns { get; set; }

        protected void Page_Init(object sender, EventArgs e)
        {
            _showChildren = Column.GetAttributeOrDefault<ShowChildTablesAttribute>();

            if (ChildMetaForeignKeyColumn != null)
            {
                EntityDataSource1.ContextTypeName = Column.ChildTable.DataContextType.FullName;
                EntityDataSource1.EntitySetName = Column.ChildTable.Name;
                EntityDataSource1.AutoGenerateWhereClause = true;

                // get an instance of the MetaTable
                table = EntityDataSource1.GetTable();

                // force the ForeignKey Column Values to be shown
                EntityDataSource1.Include = table.ForeignKeyColumnsNames;

                // set the ListView's MetaTable
                ListView1.SetMetaTable(table);

                // enable update, delete and insert
                EntityDataSource1.EnableDelete = _showChildren.EnableDelete;
                EntityDataSource1.EnableInsert = _showChildren.EnableInsert;
                EntityDataSource1.EnableUpdate = _showChildren.EnableUpdate;

                CommandButtons enabledButtons = CommandButtons.NoButtons;
                var tablePermissions = table.GetPermissions(Roles.GetRolesForUser());
                foreach (var tp in tablePermissions)
                {
                    var action = tp.Actions;
                    enabledButtons = _showChildren.EnableDelete && action.Contains(TableActions.Delete) ? CommandButtons.Delete : CommandButtons.NoButtons;
                    enabledButtons = _showChildren.EnableDetails && action.Contains(TableActions.Details) ? (enabledButtons | CommandButtons.Details) : enabledButtons;
                    enabledButtons = _showChildren.EnableUpdate && action.Contains(TableActions.Edit) ? (enabledButtons | CommandButtons.Edit) : enabledButtons;
                    enabledButtons = _showChildren.EnableInsert && action.Contains(TableActions.Insert) ? (enabledButtons | CommandButtons.Insert) : enabledButtons;
                }
                enabledButtons = _showChildren.EnableDelete ? CommandButtons.Delete : CommandButtons.NoButtons;
                enabledButtons = _showChildren.EnableDetails ? (enabledButtons | CommandButtons.Details) : enabledButtons;
                enabledButtons = _showChildren.EnableUpdate ? (enabledButtons | CommandButtons.Edit) : enabledButtons;
                enabledButtons = _showChildren.EnableInsert ? (enabledButtons | CommandButtons.Insert) : enabledButtons;
                enabledButtons = _showChildren.EnableRefresh ? (enabledButtons | CommandButtons.Refresh) : enabledButtons;

                // add dynamic validator for each mode allowed on table
                var modes = EnumWebExtensionMethods.GetEnumList(typeof(ListViewTemplateMode));
                foreach (var item in modes)
                {
                    var validationGroup = String.Format("{0}_{1}", table.Name, item.Text);
                    var validationSummary = new ValidationSummary()
                    {
                        ValidationGroup = validationGroup,
                        CssClass = "DDValidator",
                        EnableClientScript = true,
                        HeaderText = "List of validation errors"
                    };
                    PlaceHolder1.Controls.Add(validationSummary);

                    var dynamicValidator = new DynamicValidator()
                    {
                        ControlToValidate = "ListView1",
                        ValidationGroup = validationGroup,
                        CssClass = "DDValidator",
                        Display = ValidatorDisplay.None,
                        Text = "*"
                    };
                    PlaceHolder1.Controls.Add(dynamicValidator);
                }

                // get templates for list view
                var hideColumns = new String[] { ChildMetaForeignKeyColumn.Name };
                ListView1.GetTemplates(table, 
                    enabledButtons, 
                    table.Name, 
                    "DDGridView", 
                    hideColumns, 
                    false,
                    commandCellPosition: CommandCellPosition.Left);

                // hide insert row
                ListView1.InsertItemPosition = InsertItemPosition.None;

                // set the data key names
                ListView1.DataKeyNames = Column.ChildTable.GetDataKeysNames();
            }
            else
            {
                // throw an error if set on column other than MetaChildrenColumns
                throw new InvalidOperationException("The GridView FieldTemplate can only be used with MetaChildrenColumns");
            }
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            // add where and insert parameters
            if (ChildMetaForeignKeyColumn != null)
            {
                // get FK to PK dictionary supporting composite keys
                var keys = new Dictionary<String, String>();
                var thisPrimaryKeys = Table.PrimaryKeyColumns.ToArray();
                var childrenForeignKeys = ChildMetaForeignKeyColumn.ForeignKeyNames.ToArray();
                for (int i = 0; i < thisPrimaryKeys.Length; i++)
                {
                    keys.Add(childrenForeignKeys[i], thisPrimaryKeys[i].Name);
                }

                // setup the GridView's Where and Insert parameters
                // and support composite foreign keys
                foreach (String fkName in ChildMetaForeignKeyColumn.ForeignKeyNames)
                {
                    // get the current PK column component
                    var fkColumn = Column.ChildTable.GetColumn(fkName);

                    // setup parameter
                    var param = new Parameter();
                    param.Name = fkColumn.Name;
                    param.Type = fkColumn.TypeCode;

                    //// get key values from route
                    //if (table.GetColumnValuesFromRoute(Context).Keys.Contains(keys[fkName]))
                    //    param.DefaultValue = table.GetColumnValuesFromRoute(Context)[keys[fkName]].ToString();
                    //else
                    //    param.DefaultValue = Request.QueryString[keys[fkName]];

                    // get key values from routing system
                    var values = Page.RouteData.Values;
                    param.DefaultValue = values[keys[fkName]].ToString();

                    // add the where clause
                    if (EntityDataSource1.WhereParameters[param.Name] == null)
                        EntityDataSource1.WhereParameters.Add(param);

                    // add the insert clause
                    if (EntityDataSource1.InsertParameters[param.Name] == null)
                        EntityDataSource1.InsertParameters.Add(param);
                }
            }
        }

        protected void ListView1_ItemCommand(object sender, ListViewCommandEventArgs e)
        {
            // show insert row
            if (e.CommandName == "ShowInsert")
                ListView1.InsertItemPosition = InsertItemPosition.FirstItem;

            // do refresh
            if (e.CommandName == "Refresh")
                ListView1.DataBind();

            // hide insert row
            if (e.CommandName == "Cancel")
                ListView1.InsertItemPosition = InsertItemPosition.None;

            //if (e.CommandName == "Edit" && !_showChildren.EnableInLineEdit)
            //    Response.Redirect(table.GetActionPath(PageAction.Edit, e.Item));
        }

        protected void ListView1_ItemInserted(object sender, ListViewInsertedEventArgs e)
        {
            // hide insert row
            ListView1.InsertItemPosition = InsertItemPosition.None;
        }

        protected void ListView1_ItemDataBound(object sender, ListViewItemEventArgs e)
        {
            if (e.Item.ItemType == ListViewItemType.DataItem && _showChildren.DisableInLineEdit)
            {
                var entity = e.Item.DataItem.GetEntity();
                var url = table.GetActionPath(PageAction.Edit, entity);
                var editButton = e.Item.FindIButtonControlRecursive("Edit");
                if (editButton != null)
                    editButton.PostBackUrl = url;
            }
        }
    }
}